﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "CmdCreateStructureRoof.h"
#include "GmUiStructureCommandRegister.h"
#include "StructureCmdIds.h"
#include "CmdStatusUtils.h"
#include "IModelView.h"
#include "GbmpModelViewTypes.h"
#include "StructureDefaultFamilyNames.h"
#include "UiCommonDialog.h"
#include "UserTransactionGroupUtils.h"
#include "IUserTransaction.h"
#include "StructureEditModeTypes.h"
#include "IEditMode.h"
#include "IStructureRoofEditModeBehavior.h"
#include "IUiDocument.h"
#include "ICommandManager.h"
#include "StructureCmdParamIds.h"
#include "CommandParameters.h"
#include "GbmpBuiltInCategoryUniIdentitiesNew.h"
#include "StructureInstancePresetParameterUtils.h"
#include "IFamily.h"
#include "StructureFamilyUtils.h"
#include "IInstanceType.h"
#include "UiDocumentViewUtils.h"

#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"


using namespace gcmp;

REGISTER_GM_COMMAND(CmdCreateStructureRoof)

CmdCreateStructureRoof::CmdCreateStructureRoof()
    : GbmpCommandBase(ID_CMD_CREATE_STRUCTURE_ROOF)
{
}

bool CmdCreateStructureRoof::IsEnabled() const
{
    CMD_ONLY_ENABLE_IN_PROJECT_ENVIRONMENT
}

bool CmdCreateStructureRoof::IsVisible() const
{
    CMD_ONLY_VISIBLE_IN_PROJECT_ENVIRONMENT
}

StructureFamilyUiUtils::FamilyCreators CmdCreateStructureRoof::GetDefaultFamilyCreators() const
{
    StructureFamilyUiUtils::FamilyCreators defaultFamilyCreators
    {
        { DEFAULT_STRUCTURE_ROOF_FAMILY_NAME, BuiltInStructureFamilies::CreateBuiltInRoofFamilyDocument }
    };

    return defaultFamilyCreators;
}

std::wstring CmdCreateStructureRoof::GetDefaultFamilyName() const
{
    return DEFAULT_STRUCTURE_ROOF_FAMILY_NAME;
}

UniIdentity CmdCreateStructureRoof::GetCategory() const
{
    UniIdentity categoryUid = BuiltInCategoryUniIdentities::BICU_NEW_ROOF;
    return categoryUid;
}

Int32 CmdCreateStructureRoof::GetCategorySecondKey() const
{
    return 0;
}

bool CmdCreateStructureRoof::CheckRunTimeEnvironment() const
{
    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IModelView* pModelView = UiDocumentViewUtils::GetCurrentModelView();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");


    const std::wstring& viewType = pModelView->GetUserDataId();

    if (PlanViewType != viewType && View3DViewType != viewType)
    {
        UiCommonDialog::ShowMessageBox(GBMP_TR(L"绘制屋顶"), GBMP_TR(L"此视图下不支持绘制屋顶"), (int)UiCommonDialog::ButtonType::OK);
        return nullptr;
    }

    IEditMode* pTopEditMode = IEditMode::GetTopActiveEditMode(pDoc);
    if (pTopEditMode != nullptr)
    {
        UiCommonDialog::ShowMessageBox(GBMP_TR(L"警告"), GBMP_TR(L"正在编辑屋顶，不能重新创建实例！"), (int)UiCommonDialog::ButtonType::OK);
        return false;
    }

    return true;
}

OwnerPtr<IAction> CmdCreateStructureRoof::ExecuteCommand(const CommandParameters& cmdParams)
{
    if (!CheckRunTimeEnvironment())
    {
        return nullptr;
    }

    IDocument* pDoc = UiDocumentViewUtils::GetCurrentDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IUiDocument* pUIDoc = UiDocumentViewUtils::GetCurrentUiDocument();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pDoc, L"pDoc为空",L"GDMPLab",L"2024-03-30");

    IModelView* pModelView = UiDocumentViewUtils::GetCurrentModelView();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pModelView, L"pModelView为空",L"GDMPLab",L"2024-03-30");

    // 创建内建屋顶族
    StructureFamilyUiUtils::FamilyCreators defaultFamilyCreators = this->GetDefaultFamilyCreators();
    StructureFamilyUiUtils::CreateFamilies(pDoc, defaultFamilyCreators);

    // 获取新创建实例的族名称、实例类型
    std::wstring familyName;
    std::wstring instanceType;
    {
        // 从命令参数读取
        auto itor = cmdParams.find(ID_CMD_PARAM_FAMILY_NAME);
        if (itor != cmdParams.end())
        {
            familyName = itor->second.AsWString();
        }
        itor = cmdParams.find(ID_CMD_PARAM_INSTANCE_TYPE);
        if (itor != cmdParams.end())
        {
            instanceType = itor->second.AsWString();
        }
    }
    if (familyName.empty() || instanceType.empty())
    {
        StructureInstancePresetParameterUtils::GetPresetFamilyNameAndInstanceType(pDoc, this->GetCategory(),
            this->GetCategorySecondKey(), familyName, instanceType);
    }
    if (familyName.empty())
    {
        familyName = GetDefaultFamilyName();
    }
    const IFamily* pFamily = IFamily::GetFamilyByName(pDoc, familyName);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pFamily, L"pFamily为空",L"GDMPLab",L"2024-03-30");

    if (instanceType.empty())
    {
        bool bOk = StructureFamilyUtils::GetFirstInstanceType(pFamily, instanceType);
        DBG_WARN_AND_RETURN_NULLPTR_UNLESS(bOk, L"GetFirstInstanceType失败",L"GDMPLab",L"2024-03-30");
    }
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(!instanceType.empty(), L"instanceType为空",L"GDMPLab",L"2024-03-30");

    const IInstanceType* pInstanceType = pFamily->GetInstanceTypeByName(instanceType);
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pInstanceType, L"pInstanceType为空",L"GDMPLab",L"2024-03-30");

    // 事务组
    int groupId;
    UserTransactionGroupUtils::Start(pDoc, GBMP_TR(L"创建屋顶"), groupId);

    OwnerPtr<IUserTransaction> opTransaction = IUserTransaction::Create(pDoc, GBMP_TR(L"开始绘制轮廓"));

    IEditMode* pProfileEditMode = IEditMode::Get(pDoc, StructureEditModeTypes::StructureRoofProfileModeType);
    if (!pProfileEditMode)
    {
        pProfileEditMode = IEditMode::Create(pDoc, IStructureRoofEditModeBehavior::Create());
    }
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pProfileEditMode, L"pProfileEditMode为空",L"GDMPLab",L"2024-03-30");

    // 开启编辑模式
    IStructureRoofEditModeBehavior* pProfileEditModeBehavior = quick_cast<IStructureRoofEditModeBehavior>(pProfileEditMode->GetEditModeBehavior());
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pProfileEditModeBehavior, L"pProfileEditModeBehavior为空",L"GDMPLab",L"2024-03-30");

    pProfileEditModeBehavior->SetEditingFamilyId(pFamily->GetElementId());
    pProfileEditModeBehavior->SetEditingInstanceTypeId(pInstanceType->GetElementId());

    pProfileEditMode->StartEditing(pDoc, ElementId::InvalidID, true, false);

    opTransaction->Commit();

    pUIDoc->UpdateView();

    // 启动绘制屋顶轮廓线的命令
    ICommandManager* pCommandManager = ICommandManager::Get();
    DBG_WARN_AND_RETURN_NULLPTR_UNLESS(pCommandManager, L"pCommandManager为空",L"GDMPLab",L"2024-03-30");
    pCommandManager->SendCommand(ID_CMD_STRUCTURE_SHOW_ROOF_PROFILE_SLOPE_RIBBON_CONTEXT);

    return nullptr;
}
